package com.example.demo.widget.chart.pie

import android.content.Context
import android.graphics.*
import android.os.Build
import android.support.annotation.ColorInt
import android.support.annotation.RequiresApi
import android.util.AttributeSet
import android.view.View
import com.example.demo.Logger
import com.example.demo.R
import com.example.demo.widget.chart.ChartData
import com.example.demo.widget.chart.utils.ChartDataUtils
import com.example.demo.widget.chart.utils.DrawTextUtils
import com.example.demo.widget.chart.utils.MathUtils
import kotlin.math.ceil
import kotlin.math.min
import kotlin.math.roundToInt

/**
 * 饼状统计图
 *
 * @author wangheng
 */
class ChartPieView: View {
    companion object {
        private const val TAG = "ChartPieView"

        private const val START_ANGLE = -90f
        private const val TOTAL_ANGLE = 360f
    }
    constructor(context: Context?) : super(context){
        initView(context,null)
    }
    constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs){
        initView(context,attrs)
    }
    constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(
        context,
        attrs,
        defStyleAttr
    ){
        initView(context,attrs)
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    constructor(
        context: Context?,
        attrs: AttributeSet?,
        defStyleAttr: Int,
        defStyleRes: Int
    ) : super(context, attrs, defStyleAttr, defStyleRes){
        initView(context,attrs)
    }

    private var mData: ChartData? = null
    private var mRadius: Float = 0f
    private var mCenterX: Float = 0f
    private var mCenterY: Float = 0f
    private var mChartRectF = RectF()

    private var mChartPaddingSize = 1f
    private var mChartPaddingColor = Color.WHITE

    private var mCommentTopTextBold = false
    private var mCommentTopTextPadding = 5f
    private var mCommentTopTextSize = 20f
    private var mCommentTopTextColor = Color.BLACK

    private var mCommentBottomTextBold = false
    private var mCommentBottomTextPadding = 5f
    private var mCommentBottomTextSize = 20f
    private var mCommentBottomTextColor = Color.BLACK

    private var mCommentLineSize = 1f

    private var mChartWidthRatio = 1f

    private var mChartPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var mChartPaddingPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var mCommentLinePaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var mCommentTopTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)
    private var mCommentBottomTextPaint = Paint(Paint.ANTI_ALIAS_FLAG)

    // 帮助类
    private var mChartCommentHelper = PieChartHelper()
    private var mDrawRect = RectF()

    private fun initView(context: Context?, attrs: AttributeSet?) {
        if(context != null){
            val ta = context.obtainStyledAttributes(attrs, R.styleable.ChartPieView)
            // app:pie_chart_padding_size 两个间隔之间的大小
            mChartPaddingSize = ta.getDimension(R.styleable.ChartPieView_pie_chart_padding_size,mChartPaddingSize)
            // app:pie_chart_padding_color 间隔线的颜色
            mChartPaddingColor = ta.getColor(R.styleable.ChartPieView_pie_chart_padding_color,mChartPaddingColor)

            // 注释线-顶部文字
            mCommentTopTextBold = ta.getBoolean(R.styleable.ChartPieView_pie_comment_top_text_bold,mCommentTopTextBold)
            mCommentTopTextSize = ta.getDimension(R.styleable.ChartPieView_pie_comment_top_text_size,mCommentTopTextSize)
            mCommentTopTextColor = ta.getColor(R.styleable.ChartPieView_pie_comment_top_text_color,mCommentTopTextColor)
            mCommentTopTextPadding = ta.getDimension(R.styleable.ChartPieView_pie_comment_top_text_padding,mCommentTopTextPadding)

            // 注释线-底部文字
            mCommentBottomTextBold = ta.getBoolean(R.styleable.ChartPieView_pie_comment_bottom_text_bold,mCommentBottomTextBold)
            mCommentBottomTextSize = ta.getDimension(R.styleable.ChartPieView_pie_comment_bottom_text_size,mCommentBottomTextSize)
            mCommentBottomTextColor = ta.getColor(R.styleable.ChartPieView_pie_comment_bottom_text_color,mCommentBottomTextColor)
            mCommentBottomTextPadding = ta.getDimension(R.styleable.ChartPieView_pie_comment_bottom_text_padding,mCommentBottomTextPadding)

            // 注释线
            mCommentLineSize = ta.getDimension(R.styleable.ChartPieView_pie_comment_line_size,mCommentLineSize)

            // 宽度占可绘制区域的百分比
            mChartWidthRatio = ta.getFloat(R.styleable.ChartPieView_pie_chart_width_ratio,mChartWidthRatio)

            ta.recycle()
        }

        // 初始化Paint们
        mChartPaint.style = Paint.Style.FILL

        initLinePaint(mChartPaddingPaint,mChartPaddingSize,mChartPaddingColor)
        initLinePaint(mCommentLinePaint,mCommentLineSize,Color.BLACK)

        initTextPaint(mCommentTopTextPaint,mCommentTopTextSize,mCommentTopTextColor)
        mCommentTopTextPaint.isFakeBoldText = mCommentTopTextBold

        initTextPaint(mCommentBottomTextPaint,mCommentBottomTextSize,mCommentBottomTextColor)
        mCommentBottomTextPaint.isFakeBoldText = mCommentBottomTextBold


        // 给帮助类设置信息
        mChartCommentHelper.mCommentLineSize = mCommentLineSize
        mChartCommentHelper.mChartSize = 0f
        mChartCommentHelper.mCommentBottomTextPadding = mCommentBottomTextPadding
        mChartCommentHelper.mCommentBottomTextPaint = mCommentBottomTextPaint
        mChartCommentHelper.mCommentTopTextPadding = mCommentTopTextPadding
        mChartCommentHelper.mCommentTopTextPaint = mCommentTopTextPaint
    }

    private fun initLinePaint(paint: Paint,size: Float,@ColorInt color: Int){
        paint.style = Paint.Style.STROKE
        paint.strokeWidth = size
        paint.color = color
    }

    private fun initTextPaint(paint: Paint,textSize: Float,@ColorInt color: Int){
        paint.textSize = textSize
        paint.color = color
    }

    private fun receiveDrawInfo(widthSize: Int, heightSize: Int) {
        mChartRectF.set(mCenterX - mRadius,
            mCenterY - mRadius,
            mCenterX + mRadius,
            mCenterY + mRadius)

        // 给帮助类设置信息
        mChartCommentHelper.mRadius = mRadius
        mChartCommentHelper.mCenterX = mCenterX
        mChartCommentHelper.mCenterY = mCenterY

        mDrawRect.left = paddingLeft.toFloat()
        mDrawRect.right = (widthSize - paddingRight).toFloat()
        mDrawRect.top = paddingTop.toFloat()
        mDrawRect.bottom = (heightSize - paddingBottom).toFloat()
        mChartCommentHelper.mDrawRect = mDrawRect

        // 收集信息
        mChartCommentHelper.calculateCommentInfo()
    }

    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val widthMode = MeasureSpec.getMode(widthMeasureSpec)
        val widthSize = MeasureSpec.getSize(widthMeasureSpec)
        if(widthMode == MeasureSpec.EXACTLY && widthSize > 0){
            val heightMode = MeasureSpec.EXACTLY

            val spaceWidth = (widthSize - paddingLeft - paddingRight) * (1 - mChartWidthRatio)
            mRadius = ((widthSize - paddingLeft - paddingRight) * mChartWidthRatio) / 2f
            val halfSpaceWidth = spaceWidth / 2
            // 设置左右距离
            mChartCommentHelper.setLeftRightSpace(halfSpaceWidth)

            val bottomHeight = mChartCommentHelper.getPieBottomHeight(halfSpaceWidth)
            val topHeight = mChartCommentHelper.getPieTopHeight(halfSpaceWidth)


            mCenterX = paddingLeft + halfSpaceWidth + mRadius
            mCenterY = paddingTop + topHeight + mRadius

            val heightSize = ceil(paddingTop + paddingBottom + 2 * mRadius + topHeight + bottomHeight).roundToInt()
            Logger.i(TAG,"${mRadius}heightSize:$heightSize spaceWidth:$spaceWidth,bottomHeight:$bottomHeight,topHeight:$topHeight")
            val hSpec = MeasureSpec.makeMeasureSpec(heightSize,heightMode)
            super.onMeasure(widthMeasureSpec, hSpec)

            receiveDrawInfo(widthSize,heightSize)

        }else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        }
    }

    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)
        if(canvas != null) {
            drawItemList(canvas)
            drawTextInfo(canvas)
        }
    }

    private val mPaddingPointList = ArrayList<PointF>()

    // 绘制列表
    private fun drawItemList(canvas: Canvas) {
        val list = mData ?.itemList ?: return
        val total = mData?.getItemValueTotal() ?: return

        if(list.size == 0 || total <= 0){
            return
        }

        val listSize = list.size
        val needDrawPadding = mChartPaddingSize > 0 && listSize > 1
        if(needDrawPadding){
            mPaddingPointList.clear()
        }
        for(index in 0 until listSize){
            val item = list[index]
            mChartPaint.color = item.color
            canvas.drawArc(mChartRectF,item.startAngle,item.swipeAngle,true,mChartPaint)
            if(needDrawPadding) {
                val angle = item.startAngle + item.swipeAngle
                mPaddingPointList.add(
                    MathUtils.getPointF(
                        mCenterX,
                        mCenterY,
                        mRadius,
                        angle
                    )
                )
            }
        }
        if(needDrawPadding && mPaddingPointList.size > 0){
            mPaddingPointList.forEach {
                canvas.drawLine(mCenterX,mCenterY,it.x,it.y,mChartPaddingPaint)
            }
        }
    }

    private val path = Path()

    // 绘制文字
    private fun drawTextInfo(canvas: Canvas) {
        val list = mData?.itemList ?: return
        val size = list.size
        if(size == 0){
            return
        }
        list.forEach {
            // 绘制上面的文字
            DrawTextUtils.drawTextOnRectCenter(canvas,mCommentTopTextPaint,it.title,it.titleRect)
            // 绘制下面的文字
            DrawTextUtils.drawTextOnRectCenter(canvas,mCommentBottomTextPaint,it.subTitle,it.subTitleRect)
            // 绘制第一条线段
            mCommentLinePaint.color = it.color
            val firstPoint = it.firstPoint
            val secondPoint = it.secondPoint
            val thirdPoint = it.thirdPoint

//            path.reset()
//            path.moveTo(firstPoint.x,firstPoint.y)
//            val controlX = firstPoint.x + (secondPoint.x - firstPoint.x) / 2f
//            val controlY = min(firstPoint.y,secondPoint.y) - mCommentTopTextSize - mCommentTopTextPadding * 2
//            path.quadTo(controlX,controlY,secondPoint.x,secondPoint.y)
//            canvas.drawPath(path,mCommentLinePaint)
            canvas.drawLine(firstPoint.x,firstPoint.y,secondPoint.x,secondPoint.y,mCommentLinePaint)
            // 绘制第二条线段
            canvas.drawLine(secondPoint.x,secondPoint.y,thirdPoint.x,thirdPoint.y,mCommentLinePaint)
        }
    }

    fun setData(data: ChartData?) {
        mData = data
        // 给帮助类设置数
        mChartCommentHelper.mList = mData?.itemList
        // 收集每一个item开始和扫过的角度的信息
        ChartDataUtils.receiveItemAngleInfo(mData, START_ANGLE, TOTAL_ANGLE)

        // 重新布局
        requestLayout()
    }
}